#include <macro.h>

#define BOARD_NUM (GetWord(@rw0@, 1) + 1) // 主板数量
#define BOARD_1 1
#define BOARD_2 2
#define BOARD_3 3
#define BOARD_4 4

#define PLUG_A 0
#define PLUG_B 1
#define PLUG_C 2
#define PLUG_D 3

#define Dual_Screen_Mode GetWord(@rw0@,30)			// 双屏设置	
#define Screen_Communication GetWord(@srw0@, 10205)	// com1通讯方式(0：232  2：485-2)

#define STOP_DISPLAY_BASE_ADDR	631		// LW631
#define TEMP_BASE_ADDR 			1000	// LW1000

typedef enum {
  STOP_NONE = 0,
  STOP_BY_HAND,		// 手动关机
  STOP_BY_PASSWORD,	// 密码关机
  STOP_BY_CARD		// 刷卡关机

} Stop_Methond_Type;   // 关机方式

typedef enum {
  TMEP_MAX_ALLOW_SINGLE = 0,	// 单体电池最高允许温度
  TMEP_MAX_CURRENT_SINGLE		// 单体电池最高实时温度

} Temp_Type;   // 温度种类

// 将屏的软件版本号更新到主板
void update_HMI_soft_version(MacroOper macroOper) {
	SetWord(@4x0@, 290, GetWord(@lw0@, 1460));
	SetWord(@4x0@, 289, GetWord(@lw0@, 1468));
}

// 关闭双屏模式时，若通讯方式为232则改成485-2 (仅单主板使用)
void reset_com1_type(MacroOper macroOper) {
	if((Dual_Screen_Mode == 0) && (Screen_Communication == 0)) {
		SetWord(@srw0@, 10205, 2);
		SetBit(@SRB20@, 0, 1);
	}
}

// 主页显示 新双枪一车与双枪切换按钮 (仅单主板使用)
void gun_mode_switch_homepage(MacroOper macroOper) {
	if(GetBit(@lb0@, 50) == 1) {
		if((GetWord(@4x0@, 208) == 5) || (GetWord(@4x0@, 208) == 6)) { //参数设置为新双枪一车或新四车&双枪一车置标记  断电保持
			SetWord(@rw0@,3,1);
		}
		else {
			SetWord(@rw0@,3,0);
		}
		
		SetBit(@lb0@, 50, 0);
	}
}

void set_temp_display_value(MacroOper macroOper, int board_index, int plug_index, int temptype, int temp) {
	if(board_index == BOARD_1) {
		SetWord(@lw0@, TEMP_BASE_ADDR + plug_index + 4 * temptype, temp);
	}
	else {
		SetWord(@lw0@, TEMP_BASE_ADDR + 8 + board_index - BOARD_2 + 3 * temptype, temp);
	}
}

// 温度值显示校准（-50 偏移）
void Temp_calibration(MacroOper macroOper, int board_index, int plug_index) {
	unsigned short on_off_state, allow_max_temp, max_temp;
	if(plug_index == 0) {
		on_off_state = GetWord(@4x0@, 16);
		allow_max_temp = GetWord(@4x0@, 66);
		max_temp = GetWord(@4x0@, 67);
	}
	else if(plug_index == 1) {
		on_off_state = GetWord(@4x0@, 116);
		allow_max_temp = GetWord(@4x0@, 166);
		max_temp = GetWord(@4x0@, 167);
	}
	else if(plug_index == 2) {
		on_off_state = GetWord(@4x0@, 616);
		allow_max_temp = GetWord(@4x0@, 666);
		max_temp = GetWord(@4x0@, 667);
	}
	else if(plug_index == 3){
		on_off_state = GetWord(@4x0@, 716);
		allow_max_temp = GetWord(@4x0@, 766);
		max_temp = GetWord(@4x0@, 767);
	}
	
	if(on_off_state == 1) { // 充电中
		// 校准单体最高允许温度
		if( allow_max_temp == 0) {
			set_temp_display_value(macroOper, board_index, plug_index, TMEP_MAX_ALLOW_SINGLE, allow_max_temp);
		}
		else {
			set_temp_display_value(macroOper, board_index, plug_index, TMEP_MAX_ALLOW_SINGLE, allow_max_temp - 50);
		}
		
		// 校准单体最高温度
		if( max_temp == 0) {
			set_temp_display_value(macroOper, board_index, plug_index, TMEP_MAX_CURRENT_SINGLE, max_temp);
		}
		else {
			set_temp_display_value(macroOper, board_index, plug_index, TMEP_MAX_CURRENT_SINGLE, max_temp - 50);
		}
	}
}

void sync_sys_pass_L1(MacroOper macroOper) {
	unsigned short data[20];
	GetMemEx(data,@srw0@,10110,8,DATA_INT16);
	SetMemEx(data,@4x0@,2238,8,DATA_INT16);
}

void Windows_Jump(MacroOper macroOper) {
	int Boad_UpMessage = GetWord(@4x0@, 3604);
	int JumpAdress = GetWord(@4x0@, 339);

	// 主板控制页面跳转
	if(Boad_UpMessage != 0) {
		if(Boad_UpMessage == 60) {
			SetWord(@lw0@, 1452, 4);
		}
		else if(Boad_UpMessage == 61) {
			SetWord(@lw0@, 1452, 5);
		}
		else if(Boad_UpMessage == 62) {
			SetWord(@lw0@, 1452, 6);
		}
		else if(Boad_UpMessage == 63) {
			SetWord(@lw0@, 1452, 7);
		}
		
		SetWord(@4x0@, 3604, 0);
	}

	// 主板下发弹窗信息
	if(JumpAdress > 0) {
		SetWord(@lw0@, 10003, JumpAdress); // 调试使用
		
		// 辅源选择弹窗(预留到30)
		if (( JumpAdress > 0) && (JumpAdress <= 4)) {
			SetWord(@lw0@, 1453, JumpAdress + 52);//52、53、54、55
		}
		// 账户信息弹窗
		else if( JumpAdress == 5) { 
			SetWord(@lw0@, 1453, 56);
		}
		// 密码输入弹窗
		else if( JumpAdress == 6) {	
			SetWord(@lw0@, 1453, 50);
		}
		// 消息弹窗(一个显示控件最多显示 256 个状态值)
		else if(( JumpAdress >= 30) && (JumpAdress <= 285)) {
			SetWord(@lw0@, 8, 1);
			SetWord(@lw0@, 1431, JumpAdress - 30);
			
			SetWord(@lw0@, 1453, 51);
		}
		else if ((JumpAdress >= 286) && (JumpAdress <= 541)) {
			SetWord(@lw0@, 8, 2);
			SetWord(@lw0@, 1432, JumpAdress - 286);
			
			SetWord(@lw0@, 1453, 51);
		}
	}
	else {
		SetWord(@lw0@, 1453, 0);//主控板将4X339置0时，关闭弹窗
	}
}

unsigned short Int16ToBCD(unsigned short v) {
	return (((v / 1000) % 10) << 12) + (((v / 100) % 10) << 8) + (((v / 10) % 10) << 4) + (v % 10);
}

unsigned short BCDToInt16(unsigned short v) {
	return (((v >> 12) & 0x0f) * 1000) + (((v >> 8) & 0x0f) * 100) + (((v >> 4) & 0x0f) * 10) + (v & 0x0f);
}

void time_update(MacroOper macroOper) {
  	unsigned short i = 0, err = 0;
	
	unsigned short board_time[20] = {0};  // BCD 从主板获取的时间
	unsigned short buff_hex[10] = {0};	
	unsigned short screen_time[10] = {0}; // hex 从屏获取的时间
	unsigned short buff_bcd[10] = {0};
	
	unsigned short read_cnt = 0;

	// 仅485屏通讯时同步时间	
	if(Screen_Communication == 2) {
		// 读时间更新命令，和主板的设定时间
		while(err != 1) {
			err = GetMemEx(board_time, @4x0@, 288, 22, DATA_INT16);
	    	read_cnt++;
			if(read_cnt > 3)	return;	// 超过3次通讯异常，跳出循环
			// 读不到数据直接退出宏，不执行下面语句
		}
		
	    /***   主板下发时间更新命令, 将主板设定时间(database 288,293)更新到屏幕   ***/
	    if(board_time[0] == 1) {
	    	for(i=0; i<6; i++) {
				buff_hex[i]=BCDToInt16(board_time[10-i]);
			}
			
			err = 0;
			err = SetMemEx(buff_hex, @srw0@, 0, 12, DATA_INT16);
			if(err != 1)	SetMemEx(buff_hex, @srw0@, 0, 12, DATA_INT16);	//写入失败，再写一次   srw0~5  年 月 日 时 分 秒
			
			// 清时间同步标志位
			// 把年月日时分读起来再判断一次
			GetMemEx(screen_time, @srw0@, 0, 12, DATA_INT16);
			if(memcmp(buff_hex, screen_time, 12)!=0) 
			SetMemEx(buff_hex, @srw0@, 0, 12, DATA_INT16);	//写入失败，再写一次
			
			// 清时间同步标志位
			SetWord(@4x0@, 288, 0);	
	    }
    
		/***   将屏幕时间同步到主板(database 281)   ***/
		// 从屏读取时间
		memset(screen_time, 0, sizeof(screen_time));
		err = 0;
		err = GetMemEx(screen_time, @srw0@, 0, 12, DATA_INT16);
		if(err != 1)	GetMemEx(screen_time, @srw0@, 0, 12, DATA_INT16);
		
		// 将时间转码
		for(i=0; i<6; i++) {
			buff_bcd[i] = Int16ToBCD(screen_time[5-i]);
		}
		
		// 将时间写入主板
		err = 0;
		err = SetMemEx(buff_bcd, @4x0@, 281, 12, DATA_INT16);
		if(err != 1)	SetMemEx(buff_bcd, @4x0@, 281, 12, DATA_INT16);   //如果写入失败，再写一次
	}
	// 232屏仅读取时间
	else if(Screen_Communication == 0) {
		// 读取主板时间，并转码为hex
		err = 0;
	    while(err != 1) {
	    	err = GetMemEx(board_time, @4x0@, 281, 12, DATA_INT16);
	    	read_cnt++;
	    	if(read_cnt > 3)	return;	//超过3次通讯异常，跳出循环
	    	//读不到数据直接退出宏，不执行下面语句
	    }
	    for(i=0;i<6;i++) {
			buff_hex[i] = BCDToInt16(board_time[5-i]);
		}
		
		// 将主板时间同步到232屏
		GetMemEx(screen_time, @srw0@, 0, 12, DATA_INT16);
		if(memcmp(buff_hex, screen_time, 12)!=0) {
			SetMemEx(buff_hex, @srw0@, 0, 12, DATA_INT16);
		}
		
		//写入失败，再写一次
		GetMemEx(screen_time, @srw0@, 0, 12, DATA_INT16);
		if(memcmp(buff_hex, screen_time, 12)!=0) {
			SetMemEx(buff_hex, @srw0@, 0, 12, DATA_INT16);
		}
	}
}

void update_qr_code(MacroOper macroOper) {
	unsigned short qr_1[128] = {0};
	unsigned short qr_2[128] = {0};
	
	// A 枪
	unsigned short err0 = GetMemEx(qr_1, @4x0@, 2450, 256, DATA_INT16);
	        if(err0!=1) GetMemEx(qr_1, @4x0@, 2450, 256, DATA_INT16);

	unsigned short err4 = SetMemEx(qr_1, @lw0@, 2000, 256, DATA_INT16);
			if(err4!=1) SetMemEx(qr_1, @lw0@, 2000, 256, DATA_INT16);
	
	// B 枪
	unsigned short err1 = GetMemEx(qr_2, @4x0@, 2578, 256, DATA_INT16);
		    if(err1!=1) GetMemEx(qr_2, @4x0@, 2578, 256, DATA_INT16);
	
	unsigned short err5 = SetMemEx(qr_2, @lw0@, 2200, 256, DATA_INT16);
			if(err5!=1) err5 = SetMemEx(qr_2, @lw0@, 2200, 256, DATA_INT16);
}

void set_stop_display_value(MacroOper macroOper, int board_index, int plug_index, int end_method) {
	if(board_index == BOARD_1) {
		SetWord(@lw0@, STOP_DISPLAY_BASE_ADDR + plug_index, end_method);
	}
	else {
		SetWord(@lw0@, STOP_DISPLAY_BASE_ADDR + 4 + board_index - BOARD_2, end_method);
	}
}

void stop_charge_display(MacroOper macroOper, int board_index, int plug_index) {
	// 检查、设置查询站号
	unsigned short current_board = GetWord(@lw0@, 11);
	if(current_board != board_index) {
		SetWord(@lw0@, 11, board_index);
	}
	
	unsigned short card_stop_enable = GetWord(@4x0@, 246);
	unsigned short pass_stop_enable = GetWord(@4x0@, 242);
	
	unsigned short start_reason, charge_state;
	if(plug_index == 0) {
		charge_state = GetWord(@4x0@, 0);
		start_reason = GetWord(@4x0@, 45);
	}
	else if(plug_index == 1) {
		charge_state = GetWord(@4x0@, 100);
		start_reason = GetWord(@4x0@, 145);
	}
	else if(plug_index == 2) {
		charge_state = GetWord(@4x0@, 600);
		start_reason = GetWord(@4x0@, 645);
	}
	else if(plug_index == 3){
		charge_state = GetWord(@4x0@, 700);
		start_reason = GetWord(@4x0@, 745);
	}
		
	// 仅启动中、充电中显示停机按钮
	if((charge_state != 2) && (charge_state != 4)) {
		set_stop_display_value(macroOper, board_index, plug_index, STOP_NONE);
		return;
	}
	
	// 刷卡启动
	if(start_reason == 1) {
		if(card_stop_enable) {
			set_stop_display_value(macroOper, board_index, plug_index, STOP_BY_CARD);
		}
		else {
			if(pass_stop_enable) {
				set_stop_display_value(macroOper, board_index, plug_index, STOP_BY_PASSWORD);
			}
			else {
				set_stop_display_value(macroOper, board_index, plug_index, STOP_BY_HAND);
			}
		}
	}
	// 非刷卡启动
	else {
		if(pass_stop_enable) {
			set_stop_display_value(macroOper, board_index, plug_index, STOP_BY_PASSWORD);
		}
		else {
			set_stop_display_value(macroOper, board_index, plug_index, STOP_BY_HAND);
		}
	}
}

void sys_poll_loop(MacroOper macroOper, int board_index) {
	// 检查、设置查询站号
	int current_board = GetWord(@lw0@, 11);
	if(current_board != board_index) {
		SetWord(@lw0@, 11, board_index);
	}
	
	update_HMI_soft_version(macroOper);
	
	// sync_sys_pass_L1(macroOper);
	Windows_Jump(macroOper);
	time_update(macroOper);
	update_qr_code(macroOper);
	
	stop_charge_display(macroOper, board_index, PLUG_A);
	Temp_calibration(macroOper, board_index, PLUG_A);
	
	if(BOARD_NUM == 1) {
		stop_charge_display(macroOper, BOARD_1, PLUG_B);
		stop_charge_display(macroOper, BOARD_1, PLUG_C);
		stop_charge_display(macroOper, BOARD_1, PLUG_D);
		
		Temp_calibration(macroOper, BOARD_1, PLUG_B);
		Temp_calibration(macroOper, BOARD_1, PLUG_C);
		Temp_calibration(macroOper, BOARD_1, PLUG_D);
		
		reset_com1_type(macroOper);
		// gun_mode_switch_homepage(macroOper);
	}
}

int MacroMain()
{	
	sys_poll_loop(macroOper, BOARD_1);
	if(BOARD_NUM == 2) {
		sys_poll_loop(macroOper, BOARD_2);
	}
	else if(BOARD_NUM == 4) {
		sys_poll_loop(macroOper, BOARD_2);
		sys_poll_loop(macroOper, BOARD_3);
		sys_poll_loop(macroOper, BOARD_4);
	}
	
	return 0;
}

